home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / GraphicsWorkshop / Source / Converters / PCX_SCRATCH / pcxwrite.m < prev    next >
Encoding:
Text File  |  1993-01-15  |  7.4 KB  |  317 lines

  1. /* ppmtopcx.c - read a portable pixmap and produce a PCX file
  2. **
  3. ** Copyright (C) 1990 by Michael Davidson.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <appkit/NXBitmapImageRep.h>
  16. #include <streams/streams.h>
  17. #include "pcxlib.h"
  18. #include "kludge.h"
  19.  
  20. #define    MAXCOLORS    256
  21. #define    MAXPLANES    4
  22.  
  23. #define cht                    0
  24. #define ppm_lookupcolor(a,b)    0
  25.  
  26. typedef void (* vfunptr)( int, int, unsigned char*, int, int );
  27.  
  28. /*
  29.  * Pointer to function returning an int
  30.  */
  31. static void PCXEncode(        NXStream    * fp, 
  32.                             int             GWidth, 
  33.                             int             GHeight, 
  34.                             int             Colors, 
  35.                             unsigned char    Red[], 
  36.                             unsigned char    Green[], 
  37.                             unsigned char    Blue[], 
  38.                             vfunptr         GetPlanes);
  39. static void PutPlane (            NXStream    *fp, 
  40.                             unsigned char    *buf, 
  41.                             int             Size );
  42. static void ReadPlanes(        int            y, 
  43.                             int             width, 
  44.                             unsigned char    *buf, 
  45.                             int             planes, 
  46.                             int             bits);
  47. static void Putword(             int             w, 
  48.                             NXStream    *fp);
  49. static void Putbyte(             int             b, 
  50.                             NXStream    *fp );
  51.  
  52. static unsigned char        *picData;
  53.  
  54. void pcxwrite(NXStream         *ifp, 
  55.             unsigned char     *data, 
  56.             unsigned char        r[256],
  57.             unsigned char        g[256],
  58.             unsigned char        b[256],
  59.             int                width,
  60.             int                height,
  61.             int                colors)
  62. {
  63.     /* All set, let's do it. */
  64.     picData = data;
  65.     PCXEncode(ifp, width, height, colors, r, g, b, ReadPlanes );
  66. }
  67.  
  68. /*****************************************************************************
  69.  *
  70.  * PCXENCODE.C    - PCX Image compression interface
  71.  *
  72.  * PCXEncode( FName, GHeight, GWidth, Colors, Red, Green, Blue, GetPlanes )
  73.  *
  74.  *****************************************************************************/
  75.  
  76. /* public */
  77.  
  78. static void PCXEncode(        NXStream    * fp, 
  79.                             int             GWidth, 
  80.                             int             GHeight, 
  81.                             int             Colors, 
  82.                             unsigned char    Red[], 
  83.                             unsigned char    Green[], 
  84.                             unsigned char    Blue[], 
  85.                             vfunptr         GetPlanes)
  86. {
  87.     int        BytesPerLine;
  88.     int        Planes;
  89.     int        BitsPerPixel;
  90.     unsigned char    *buf;
  91.     int        i;
  92.     int        n;
  93.     int        y;
  94.  
  95.     /*
  96.      * select number of planes and number of bits
  97.      * per pixel according to number of colors
  98.      */
  99.     /*
  100.      * 16 colors or less are handled as 1 bit per pixel
  101.      * with 1, 2, 3 or 4 color planes.
  102.      * more than 16 colors are handled as 8 bits per pixel
  103.      * with 1 plane
  104.      */
  105.     if (Colors > 16) {
  106.         BitsPerPixel    = 8;
  107.         Planes        = 1;
  108.     } else {
  109.         BitsPerPixel    = 1;
  110.         if (Colors > 8)
  111.             Planes = 4;
  112.         else if (Colors > 4)
  113.             Planes = 3;
  114.         else if (Colors > 2)
  115.             Planes = 2;
  116.         else
  117.             Planes = 1;
  118.     }
  119.  
  120.         /*
  121.          * Write the PCX header
  122.          */
  123.     Putbyte( 0x0a, fp);                        // .PCX magic number
  124.     Putbyte( 0x05, fp);                        // PC Paintbrush version
  125.     Putbyte( 0x01, fp);                        // .PCX run length encoding
  126.     Putbyte( BitsPerPixel, fp);                // bits per pixel
  127.  
  128.         Putword( 0, fp );                        // x1 - image left
  129.         Putword( 0, fp );                        // y1 - image top
  130.     Putword( GWidth-1, fp );                // x2 - image right
  131.     Putword( GHeight-1, fp );                // y2 - image bottom
  132.  
  133.     Putword( GWidth, fp );                    // horizontal resolution
  134.     Putword( GHeight, fp );                // vertical resolution
  135.  
  136.         /*
  137.          * Write out the Color Map for images with 16 colors or less
  138.          */
  139.     n = (Colors <= 16) ? Colors : 16;
  140.         for (i = 0; i < n; ++i) {
  141.                 Putbyte( Red[i], fp );
  142.                 Putbyte( Green[i], fp );
  143.                 Putbyte( Blue[i], fp );
  144.         }
  145.         for (; i < 16; ++i) {
  146.                 Putbyte( 255, fp );
  147.                 Putbyte( 255, fp );
  148.                 Putbyte( 255, fp );
  149.         }
  150.  
  151.     Putbyte( 0, fp);                        // reserved byte
  152.  
  153.     Putbyte( Planes, fp);                    // number of color planes
  154.  
  155.     BytesPerLine    = ((GWidth * BitsPerPixel) + 7) / 8;
  156.     Putword( BytesPerLine, fp )    ;            // number of bytes per scanline
  157.  
  158.     Putword( 1, fp);                        // pallette info
  159.  
  160.     for (i = 0; i < 58; ++i)                    // fill to end of header
  161.         Putbyte( 0, fp );
  162.  
  163.     buf    = (unsigned char *)malloc( MAXPLANES * BytesPerLine );
  164.  
  165.     for (y = 0; y < GHeight; ++y) {
  166.         (*GetPlanes)(y, GWidth, buf, Planes, BitsPerPixel);
  167.  
  168.         for (i = 0; i < Planes; ++i)
  169.             PutPlane(fp, buf + (i * BytesPerLine), BytesPerLine);
  170.     }
  171.  
  172.     /*
  173.      * color map for > 16 colors is at end of file
  174.      */
  175.     if (Colors > 16) {
  176.         Putbyte( 0x0c, fp);                    // magic for 256 colors
  177.             for (i = 0; i < Colors; ++i) {
  178.                     Putbyte( Red[i], fp );
  179.                     Putbyte( Green[i], fp );
  180.                     Putbyte( Blue[i], fp );
  181.             }
  182.             for (; i < MAXCOLORS; ++i) {
  183.                     Putbyte( 255, fp );
  184.                     Putbyte( 255, fp );
  185.                     Putbyte( 255, fp );
  186.             }
  187.     }
  188. }
  189.  
  190. static void PutPlane (            NXStream    *fp, 
  191.                             unsigned char    *buf, 
  192.                             int             Size )
  193. {
  194.     unsigned char        *end;
  195.     int                c;
  196.     int                previous;
  197.     int                count;
  198.  
  199.     end    = buf + Size;
  200.  
  201.     previous = *buf++;
  202.     count     = 1;
  203.  
  204.     while (buf < end)
  205.     {
  206.         c = *buf++;
  207.         if (c == previous && count < 63) {
  208.             ++count;
  209.             continue;
  210.         }
  211.  
  212.         if (count > 1 || (previous & 0xc0) == 0xc0) {
  213.             count |= 0xc0;
  214.             Putbyte ( count , fp );
  215.         }
  216.         Putbyte(previous, fp);
  217.         previous = c;
  218.         count    = 1;
  219.     }
  220.  
  221.     if (count > 1 || (previous & 0xc0) == 0xc0) {
  222.         count |= 0xc0;
  223.         Putbyte ( count , fp );
  224.     }
  225.     Putbyte(previous, fp);
  226. }
  227.  
  228. static unsigned long PixMap[8][16] =
  229. {
  230.     0x00000000L,    0x00000080L,    0x00008000L,    0x00008080L,
  231.     0x00800000L,    0x00800080L,    0x00808000L,    0x00808080L,
  232.     0x80000000L,    0x80000080L,    0x80008000L,    0x80008080L,
  233.     0x80800000L,    0x80800080L,    0x80808000L,    0x80808080L,
  234. };
  235.  
  236. static void ReadPlanes(        int            y, 
  237.                             int             width, 
  238.                             unsigned char    *buf, 
  239.                             int             planes, 
  240.                             int             bits)
  241. {
  242. //    static pixel        **pixels;
  243.     static int            first_time = 1;
  244.     unsigned char        *plane0, *plane1, *plane2, *plane3;
  245.     int                i, j, x;
  246.  
  247.     /*
  248.      * 256 color, 1 plane, 8 bits per pixel
  249.      */
  250.      plane0 = picData + width * y;
  251.     if (planes == 1 && bits == 8) {
  252.         for (x = 0; x < width; ++x)
  253. //            buf[x] = ppm_lookupcolor( cht, &pixels[y][x] );
  254.             buf[x] = *(plane0 + x);
  255.         return;
  256.     }
  257.  
  258.     /*
  259.      * must be 16 colors or less, 4 planes or less, 1 bit per pixel
  260.      */
  261.     if (first_time) {
  262.         for (i = 1; i < 8; ++i)
  263.             for (j = 0; j < 16; ++j)
  264.                 PixMap[i][j] = PixMap[0][j] >> i;
  265.         first_time = 0;
  266.     }
  267.  
  268.     i = (width + 7) / 8;
  269.  
  270.     plane0    = buf;
  271.     plane1    = plane0 + i;
  272.     plane2    = plane1 + i;
  273.     plane3    = plane2 + i;
  274.  
  275.     i    = 0;
  276.     x    = 0;
  277.  
  278.     while ( x < width ) {
  279.         register unsigned long    t;
  280.  
  281.         t     = PixMap[0][ppm_lookupcolor( cht, &pixels[y][x++] )];
  282.         t    |= PixMap[1][ppm_lookupcolor( cht, &pixels[y][x++] )];
  283.         t    |= PixMap[2][ppm_lookupcolor( cht, &pixels[y][x++] )];
  284.         t    |= PixMap[3][ppm_lookupcolor( cht, &pixels[y][x++] )];
  285.         t    |= PixMap[4][ppm_lookupcolor( cht, &pixels[y][x++] )];
  286.         t    |= PixMap[5][ppm_lookupcolor( cht, &pixels[y][x++] )];
  287.         t    |= PixMap[6][ppm_lookupcolor( cht, &pixels[y][x++] )];
  288.         t    |= PixMap[7][ppm_lookupcolor( cht, &pixels[y][x++] )];
  289.  
  290.         plane0[i] = t;
  291.         plane1[i] = t >> 8;
  292.         plane2[i] = t >> 16;
  293.         plane3[i++] = t >> 24;
  294.     }
  295. }
  296.  
  297. /*
  298.  * Write out a word to the PCX file
  299.  */
  300. static void Putword(             int             w, 
  301.                             NXStream    *fp)
  302. {
  303.         NXPutc( fp, w & 0xff );
  304.         NXPutc( fp, (w / 256) & 0xff );
  305. }
  306.  
  307. /*
  308.  * Write out a byte to the PCX file
  309.  */
  310. static void Putbyte(             int             b, 
  311.                             NXStream    *fp )
  312. {
  313.         NXPutc( fp, b & 0xff );
  314. }
  315.  
  316. /* The End */
  317.